package com.sd365.permission.centre.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sd365.common.core.annotation.mybatis.Pagination;
import com.sd365.common.core.annotation.stuffer.CommonFieldStuffer;
import com.sd365.common.core.annotation.stuffer.IdGenerator;
import com.sd365.common.core.annotation.stuffer.MethodTypeEnum;
import com.sd365.common.core.common.aop.MyPageInfo;
import com.sd365.common.core.common.exception.BusinessException;
import com.sd365.common.core.common.exception.code.BusinessErrorCode;
import com.sd365.common.core.common.exception.code.ServiceErrorCode;
import com.sd365.common.core.context.BaseContextHolder;
import com.sd365.common.core.mq.ActionType;
import com.sd365.common.util.BeanException;
import com.sd365.common.util.BeanUtil;
import com.sd365.permission.centre.dao.mapper.*;
import com.sd365.permission.centre.entity.*;
import com.sd365.permission.centre.pojo.dto.*;
import com.sd365.permission.centre.pojo.query.RoleQuery;
import com.sd365.permission.centre.pojo.query.UserQuery;
import com.sd365.permission.centre.pojo.vo.RoleCompanyVO;
import com.sd365.permission.centre.service.RoleService;
import com.sd365.permission.centre.service.exception.UserCentreExceptionCode;
import com.sd365.permission.centre.service.util.SendMQMessageUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class RoleServiceImpl extends AbstractBaseDataServiceImpl implements RoleService {
    @Autowired
    private SendMQMessageUtil sendMQMessageUtil;
    private static final String TABLE_NAME = "role";
    @Autowired
    private IdGenerator idGenerator;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private OrganizationMapper organizationMapper;
    @Autowired
    private TenantMapper tenantMapper;
    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleResourceMapper roleResourceMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private PositionMapper positionMapper;

    /**
     * TODO
     * @param role
     * @return
     */
    @Override
    public Boolean initRoleResourceRedis(Role role) {
        return null;
    }


    @Override
    public Boolean assignResource(RoleResourceDTO roleResourceDTO) {
        List<Long> roleIds = roleResourceDTO.getRoleIds();
        List<Long> resourceIds = roleResourceDTO.getResourceIds();
        if (roleIds == null || roleIds.isEmpty()){
            throw  new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_OTHER_EXCEPTION,new Exception("角色id为空"));
        }
        Long companyId = roleResourceDTO.getCompanyId();
        Long orgId = roleResourceDTO.getOrgId();
        Long tenantId = roleResourceDTO.getTenantId();
        for (Long roleId : roleIds){
            Role role = roleMapper.selectById(roleId);
            if (role == null){
                throw  new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE,new Exception("角色不存在"));
            }
            roleResourceMapper.deleteByRoleId(roleId);
            for (Long resourseId : resourceIds){
                RoleResource roleResource = new RoleResource();
                super.baseDataStuff4Add(roleResource);
                roleResource.setId(idGenerator.snowflakeId());
                roleResource.setRoleId(roleId);
                roleResource.setResourceId(resourseId);
                roleResource.setCompanyId(companyId);
                roleResource.setOrgId(orgId);
                roleResource.setTenantId(tenantId);
                roleResource.setVersion(1L);
                int result = roleResourceMapper.insertRoleResource(roleResource);
                if (result <= 0){
                    throw  new BusinessException(UserCentreExceptionCode.RESOURCE_ASSIGN_FAILED,new Exception("资源分配失败"));
                }
            }
        }
        return true;
    }


    @Override
    public Boolean assignUser(UserRoleDTO userRoleDTO) {
        List<Long> roleIds = userRoleDTO.getRoleIds();
        List<Long> userIds = userRoleDTO.getUserIds();
        if (roleIds == null || roleIds.isEmpty()){
            throw  new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_OTHER_EXCEPTION,new Exception("角色id为空"));
        }
        Long companyId = userRoleDTO.getCompanyId();
        Long orgId = userRoleDTO.getOrgId();
        Long tenantId = userRoleDTO.getTenantId();
        for (Long userId : userIds) {
            User user = userMapper.selectById(userId);
            if (user == null) {
                throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE, new Exception("用户不存在"));
            }
            userRoleMapper.deleteAllByUserID(userId);
            for (Long roleId : roleIds){
                UserRole userRole = new UserRole();
                super.baseDataStuff4Add(userRole);
                userRole.setId(idGenerator.snowflakeId());
                userRole.setUserId(userId);
                userRole.setRoleId(roleId);
                userRole.setCompanyId(companyId);
                userRole.setOrgId(orgId);
                userRole.setTenantId(tenantId);
                userRole.setVersion(1L);
                int result = userRoleMapper.insert(userRole);
                if (result <= 0){
                    throw new BusinessException(UserCentreExceptionCode.RESOURCE_ASSIGN_FAILED,new Exception("用户角色分配失败"));
                }
            }
        }
        return true;
    }

    @Override
    public List<Node> queryResourceByRoleId(long roleId) {
        List<Node> nodeList = roleResourceMapper.queryResourceByRoleId(roleId);
        return nodeList;
    }

    @Override
    public List<Node> selectCompany() {
        List<Node> nodeList = roleMapper.selectCompany();
        return nodeList;
    }

    @Override
    public boolean haveRole(RoleDTO roleDTO) {
        try{
            Role role = BeanUtil.copy(roleDTO,Role.class);
            role.setId(idGenerator.snowflakeId());
            role.setVersion(1L);
            Boolean flag =  roleMapper.haveRole(role) > 0;
            return flag;
        }catch (BeanException ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);
        }
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.ADD)
    public Boolean add(@Valid RoleDTO roleDTO) {
        try {
            Role role = BeanUtil.copy(roleDTO,Role.class);
            String code = role.getCode();
            if (roleMapper.selectRoleByCode(code)>0){
//                throw new Exception("角色编号不能重复");
                return false;
            }
            role.setId(idGenerator.snowflakeId());
            role.setVersion(1L);
            baseDataStuff4Add(role);
            Boolean flag = roleMapper.insert(role) > 0;
            if (flag) {
                sendMQMessageUtil.SendMessage(ActionType.INSERT,SendMQMessageUtil.EXCHANGE_NAME,TABLE_NAME,role);
            }
            return flag;
        } catch (BeanException ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);
        } catch (Exception ex) {
            throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_OTHER_EXCEPTION,ex);//new Exception("角色编号不能重复"));
            //throw new BusinessException(String.valueOf(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE.getCode()),UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE.getMessage());
        }
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.DELETE)
    public Boolean remove(Long id, Long version) {
       try {
            Example example = new Example(Role.class);
            example.createCriteria().andEqualTo("id", id).andEqualTo("version", version);
            Boolean flag = roleMapper.deleteByExample(example) > 0;
            if (flag) {
                Role role = new Role();
                role.setId(id);
                role.setVersion(version);
                sendMQMessageUtil.SendMessage(ActionType.DELETE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, role);
            }
            return flag;
        } catch (Exception e) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_REMOVE_EXCEPTION_CODE, e);
        }
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.UPDATE)
    public Boolean modify(RoleDTO roleDTO) {
        try{

            Role role = BeanUtil.copy(roleDTO, Role.class);
            super.baseDataStuff4Updated(role);
            Example example = new Example(Role.class);
            example.createCriteria().andEqualTo("id", roleDTO.getId()).andEqualTo("version", roleDTO.getVersion());
            role.setUpdatedTime(new Date());
            Boolean flag = roleMapper.updateByExample(role, example) > 0;
            if (flag) {
                sendMQMessageUtil.SendMessage(ActionType.UPDATE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, role);
            }
            return flag;
        }catch (BeanException ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);
        }
    }


    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    public List<RoleDTO> commonQuery(RoleQuery roleQuery) {
        if (roleQuery == null){
            throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_ARGUMENT_NOT_VALID, new Exception("commonQuery 方法错误"));
        }
        try{
            Role role = BeanUtil.copy(roleQuery,Role.class);
            PageHelper.startPage(roleQuery.getPageNum(),roleQuery.getPageSize());
            List<Role> roleList = roleMapper.commonQuery(role);
            Page page = (Page) roleList;
            BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
            List<RoleDTO> roleDTOList = BeanUtil.copyList(roleList,RoleDTO.class,(src, tar) -> {
                Role source = (Role) src;
                RoleDTO target = (RoleDTO) tar;
                Organization organization = source.getOrganization();
                Company company = source.getCompany();
                Tenant tenant = source.getTenant();
                target.setCompanyDTO(BeanUtil.copy(company,CompanyDTO.class));
                target.setOrganizationDTO(BeanUtil.copy(organization,OrganizationDTO.class));
                target.setTenantDTO(BeanUtil.copy(tenant,TenantDTO.class));
            });
            return roleDTOList;
        } catch (BeanException ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE, ex);
        }
    }
//        if (roleQuery.getId() == null){
//            List<Role> roleList = roleMapper.selectAll();
//            Page page = (Page) roleList;
//            BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(),page.getPages())));
//
//            List<RoleDTO> roleDTOList = BeanUtil.copyList(roleList,RoleDTO.class,(src, tar) -> {
//                Role source = (Role) src;
//                RoleDTO target = (RoleDTO) tar;
//                Organization organization = source.getOrganization();
//                Company company = source.getCompany();
//                Tenant tenant = source.getTenant();
//                target.setCompanyDTO(BeanUtil.copy(company,CompanyDTO.class));
//                target.setOrganizationDTO(BeanUtil.copy(organization,OrganizationDTO.class));
//                target.setTenantDTO(BeanUtil.copy(tenant,TenantDTO.class));
//            });
//                return roleDTOList;
//
//        }else{
//        String name = roleQuery.getName();
//        Long companyId = roleQuery.getCompanyId();
//        Long orgId = roleQuery.getOrgId();
//        Long tenantId = roleQuery.getTenantId();
//
//        Role role = new Role();
//        role.setName(name);
//        role.setCompany(companyMapper.selectById(companyId));
//        role.setOrganization(organizationMapper.selectById(orgId));
//        role.setTenant(tenantMapper.selectById(tenantId));
//
//            List<Role> roleList = roleMapper.commonQuery(role);
//
//
//            JSONObject pageInfo = new JSONObject();
//            pageInfo.put("total", ((Page) roleList).getTotal());
//            pageInfo.put("pages", ((Page) roleList).getPages());
//            BaseContextHolder.set("pageInfo", pageInfo.toJSONString());
//            return BeanUtil.copyList(roleList,RoleDTO.class,(src, tar) -> {
//                Role source = (Role) src;
//                RoleDTO target = (RoleDTO) tar;
//                Organization organization = organizationMapper.selectById(source.getOrgId());
//                Company company = companyMapper.selectById(source.getCompanyId());
//                Tenant tenant = tenantMapper.selectById(source.getTenantId());
//                target.setCompanyDTO(BeanUtil.copy(company,CompanyDTO.class));
//                target.setOrganizationDTO(BeanUtil.copy(organization,OrganizationDTO.class));
//                target.setTenantDTO(BeanUtil.copy(tenant,TenantDTO.class));
//            });
//
//
//    }
//    }


    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    public RoleDTO queryById(Long id) {
        try{
            RoleDTO roleDTO = null;
            Role role = roleMapper.selectById(id);
            if (role != null){
                 roleDTO = BeanUtil.copy(role,RoleDTO.class);
            }
            return roleDTO;
        }catch (BeanException ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);
        }
    }

    /**
     * TODO
     * @param id
     * @return
     */
    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.ADD)
    public RoleDTO copy(Long id) {
        try{
        Role role = roleMapper.selectById(id);
        if (role!=null){
            RoleDTO copy = BeanUtil.copy(role,RoleDTO.class);
            if (roleMapper.selectRoleByCode(copy.getCode())>0){
                throw new Exception("角色编号不能重复");
            }
            return copy;
        }
        }catch (Exception ex){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE,ex);
        }
        return new RoleDTO();
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.DELETE)
    public Boolean batchRemove(RoleDTO[] roleDTOS) {
        Assert.notEmpty(roleDTOS, "批量删除参数不可以为空");
        for (RoleDTO roleDTO : roleDTOS) {
            Example example = new Example(Role.class);
            example.createCriteria().andEqualTo("id", roleDTO.getId());
            int result = roleMapper.deleteByExample(example);
            if (result <= 0) {
                throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_OTHER_EXCEPTION, new Exception(String.format("删除的记录id %d 没有匹配到版本", roleDTO.getId())));
            }else{
                Role role = new Role();
                role.setId(roleDTO.getId());
                role.setVersion(roleDTO.getVersion());
                sendMQMessageUtil.SendMessage(ActionType.DELETE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, role);
            }
        }
        return true;
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    public List<UserDTO> commonQueryUser(UserQuery userQuery) {
        if (userQuery == null){
            throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_ARGUMENT_NOT_VALID, new Exception("commonQueryUser 方法错误"));
        }
        try {
            User user = BeanUtil.copy(userQuery,User.class);
            PageHelper.startPage(userQuery.getPageNum(),userQuery.getPageSize());
            List<User> userList = userMapper.commonQuery(user);
            Page page = (Page) userList;
            BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
            List<UserDTO> userDTOList = BeanUtil.copyList(userList,UserDTO.class,(src, tar) -> {
                User source = (User) src;
                UserDTO target = (UserDTO) tar;
                Organization organization = source.getOrganization();
                Company company = source.getCompany();
                Tenant tenant = tenantMapper.selectById(source.getTenantId());
                target.setCompany(BeanUtil.copy(company,CompanyDTO.class));
                target.setOrganization(BeanUtil.copy(organization,OrganizationDTO.class));
                target.setTenant(BeanUtil.copy(tenant,TenantDTO.class));
            });
            return userDTOList;
        }catch (BeanException ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATA_USER_DB_EXCEPTION_CODE, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATA_USER_DB_EXCEPTION_CODE, ex);
        }
    }

//        String name = userQuery.getName();
//        String code = userQuery.getCode();
//        String tel = userQuery.getTel();
//        Long roleId = userQuery.getRoleId();
//        Long departmentId = userQuery.getDepartmentId();
//        Long positionId = userQuery.getPositionId();
//        Long orgId = userQuery.getOrgId();
//        Long companyId = userQuery.getCompanyId();
//
//        User user = new User();
//        user.setName(name);
//        user.setCode(code);
//        user.setTel(tel);
//        user.setDepartment(departmentMapper.selectById(departmentId));
//        user.setPosition(positionMapper.selectPositionById(positionId));
//        user.setCompany(companyMapper.selectById(companyId));
//        user.setOrganization(organizationMapper.selectById(orgId));
//
//        if (roleId == null){
//            try {
//                List<User> userList = userMapper.commonQuery(user);
//                List<UserDTO> userDTOList = new ArrayList<>();
//                for (User temp : userList){
//                    UserDTO userDTO = BeanUtil.copy(temp,UserDTO.class);
//                    userDTOList.add(userDTO);
//                }
//                Page page = (Page) userDTOList;
//                BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
//                return userDTOList;
//            } catch (Exception e) {
//                throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE, e);
//            }
//        }else{
//            try {
//                List<User> userList = userMapper.commonByQueryRoleId(user,roleId);
//                List<UserDTO> userDTOList = new ArrayList<>();
//                for (User temp : userList){
//                    UserDTO userDTO = BeanUtil.copy(temp,UserDTO.class);
//                    userDTOList.add(userDTO);
//                }
//                Page page = (Page) userDTOList;
//                BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
//                return userDTOList;
//            }catch (Exception e){
//                throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE, e);
//            }
//        }
//    }

    @Override
    public RoleDTO queryUserResource(Long id) {

        User user = userMapper.selectById(id);
        List<Role> roleList = roleMapper.selectRolesByUserId(id);
        if (roleList!=null){
        List<Long> roleIdList = new ArrayList<>();
        for (Role role : roleList){
            roleIdList.add(role.getId());
        }
        List<Resource> resourceList = resourceMapper.getResourceByRoleId(roleIdList);
        List<ResourceDTO> resourceDTOList = BeanUtil.copyList(resourceList,ResourceDTO.class,(src, tar) -> {
            Resource source = (Resource) src;
            ResourceDTO target = (ResourceDTO) tar;
            Organization organization = source.getOrganization();
            Company company = source.getCompany();
            Tenant tenant = source.getTenant();
            target.setCompany(BeanUtil.copy(company,CompanyDTO.class));
            target.setOrganization(BeanUtil.copy(organization,OrganizationDTO.class));
            target.setTenant(BeanUtil.copy(tenant,TenantDTO.class));
        });
        OrganizationDTO organizationDTO = BeanUtil.copy(user.getOrganization(),OrganizationDTO.class);
        CompanyDTO companyDTO = BeanUtil.copy(user.getCompany(),CompanyDTO.class);
        Tenant tenant = tenantMapper.selectById(user.getTenantId());
        TenantDTO tenantDTO = BeanUtil.copy(tenant,TenantDTO.class);
        RoleDTO roleDTO = new RoleDTO(resourceDTOList,user.getName(),user.getCode(),user.getRemark(),organizationDTO,companyDTO,tenantDTO);
        return roleDTO;
    }else {
            throw new BusinessException(ServiceErrorCode.BASE_CRUD_SERVICE_ERROR_CODE_RETRIEVE,new Exception("查询失败"));
        }
    }

    @Override
    public RoleCompanyVO queryRoleCompanyById(Long id) {
        return null;
    }

    @Override
    public Boolean modifyRoleCompany(RoleCompanyDTO roleCompanyDTO) {
        return null;
    }
}
